A
few of the system catalogs and dynamic management views (DMVs) might be
of interest to you if you’re debugging Service Broker applications or
simply seeking a greater understanding of how Service Broker works under
the hood. Let’s take a look at some of them.
You’ve already seen sys.transmission_queue,
which is used to store undelivered messages in a particular database.
This table is very useful because it provides the reason a message is
undeliverable (in transmission_status), the date sent (in enqueue_time), a conversation identifier (conversation_handle), contract and service names (service_contract_name, to_service_name, from_service_name), and more.
Another useful catalog is sys.service_queues, which holds the definitions of the queues defined in a particular database. It has a few interesting columns:
activation_procedure— This column contains the name of the activated service program that is bound to the queue.
max_readers— This column contains the integer value specified in the CREATE QUEUE of MAX_QUEUE_READERS.
is_retention_enabled— This column contains the Boolean value of the RETENTION flag in CREATE QUEUE.
You can use the value in the object_id
column to figure out which queue is being referenced in a particular
error message, such as the following, which you may find in your
transmission queue someday: This message could not be delivered because the destination queue has been disabled. Queue ID: 325576198.
This error occurs when your activated code throws an error in its body
after receiving a message, rolls back the receive, is activated again,
and so on, until Service Broker intervenes and disables the queue. (It
usually takes three failures for this to happen.) A similar error is
raised if you set ENCRYPTION = ON and don’t set up certificates.
To see all the services in a particular database, you can query sys.services. To see all the active conversations, you can query sys.conversation_groups. The following query shows how to use these tables together:
SELECT
sq.name as QueueName,
ss.name as ServiceName,
cg.conversation_group_id as CGId
FROM sys.services ss
JOIN sys.service_queues sq
ON ss.service_queue_id = sq.object_id
LEFT JOIN sys.conversation_groups cg
ON cg.service_id = ss.service_id
To see all the contracts in a particular database, you can query sys.service_contracts. To see all the message types, you can query sys.service_message_types. These catalog views are brought together in the system table sys.service_contract_message_usages (showing message types by contract). You can also link them to sys.service_contract_usages (showing contracts by service) via the following query:
SELECT
s.Name ServiceName,
sc.Name ContractName,
smt.Name as MsgTypeName,
scmu.is_sent_by_initiator,
scmu.is_sent_by_target
FROM sys.services s
JOIN sys.service_contract_usages scu
ON scu.service_id = s.service_id
JOIN sys.service_contracts sc
ON sc.service_contract_id = scu.service_contract_id
JOIN sys.service_contract_message_usages scmu
ON scmu.service_contract_id = sc.service_contract_id
JOIN sys.service_message_types smt
ON smt.message_type_id = scmu.message_type_id
In addition, you can view any certificates you have created by querying sys.certificates, routes via sys.routes, and remote service bindings via sys.remote_service_bindings. Each side of a conversation is known as an endpoint, and you can view endpoints by querying sys.conversation_endpoints.
Five DMVs may be of interest in debugging live Service Broker applications:
sys.dm_broker_activated_tasks— Each row refers to a stored procedure being activated.
sys.dm_broker_connections— Each row refers to an in-use Service Broker network connection.
sys.dm_broker_forwarded_messages— Each row refers to a message currently being forwarded.
sys.dm_broker_queue_monitors—
Each row refers to the current behavior of a SQL Server background task
known as a queue monitor, which is responsible for activation.
sys.dm_broker_transmission_status— Each row refers to the status of a message being transmitted.
To see all the activated stored procedures in a given database, for example, you can try the following:
SELECT
d.name DBName,
sq.name QueueName,
dmbat.spid SPID,
dmbat.procedure_name ProcName
FROM sys.dm_broker_activated_tasks dmbat
JOIN sys.databases d ON
d.database_id = dmbat.database_id
AND dmbat.database_id = DB_ID()
JOIN sys.service_queues sq
ON dmbat.queue_id = sq.object_id